<?php

namespace pmvc\util;

use ArrayAccess;
use Exception;

/**
 * Utility class for using a bit mask.
 */
class BitSet
	implements ArrayAccess {

	private $value 	= 0;
	private $maxBit	= 0;

	/**
	 * Creates the object with the given mask.
	 * @param int $value
	 */
	public function __construct($value=0) {
		$this->value = $value;
		$this->maxBit	= (PHP_INT_SIZE * 8)-1;
	}

	/**
	 * Returns the current value of the mask.
	 * @return int
	 */
	public function getValue() {
		return $this->value;
	}

	/**
	 * Sets the mask.
	 * @param int $value
	 */
	public function setValue($value) {
		$this->value = $value;
	}

	/**
	 * Gets the value of the bit at the given index.
	 * @param int $bit
	 * @throws Exception
	 * @return bool
	 */
	public function get($bit) {
		if ($bit>=$this->maxBit) {
			throw new Exception("bit is larger than PHP_INT_SIZE");
		}
		$mask = pow(2, $bit);
		return ($this->value & $mask) == $mask;
	}

	/**
	 * Sets the value of the bit at the given index.
	 * @param int $bit
	 * @param bool $value
	 * @throws Exception
	 */
	public function set($bit, $value) {
		if ($bit>=$this->maxBit) {
			throw new Exception("bit is larger than PHP_INT_SIZE");
		}
		$mask = pow(2, $bit);
		if ($value===true) {
			$this->value |= $mask;
		} else {
			$this->value &= ~$mask;
		}
	}

	/**
	 * Clears the bit mask.
	 */
	public function clear() {
		$this->value = 0;
	}

	// ArrayAccess stuff

	public function offsetExists($offset) {
		return ($offset<$this->maxBit);
	}

	public function offsetGet($offset) {
		return $this->get($offset);
	}

	public function offsetSet($offset, $value) {
		return $this->set($offset, $value===true);
	}

	public function offsetUnset($offset) {
		return $this->set($offset, false);
	}
}

?>